package com.dh.convert.rule.function;

import com.dh.convert.exception.ConvertValueException;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorBoolean;
import com.googlecode.aviator.runtime.type.AviatorObject;
import org.apache.commons.lang3.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * @fileName: CertCheckFunction.java
 * @author: Wenjing.Chen
 * @date: 2019/2/25 13:48
 * @version: v1.0.0
 * @since JDK 1.8
 */
public class CertCheckFunction extends AbstractFunction {

	private static final String MAIL_DATE_DT_PART_FORMAT = "yyyyMMdd";

	/**
	 * 身份证长期有效格式.
	 */
	private static final String CERT_PERMANENT = "长期 || 99991231 || 20991231";

	private static final String LEAP_SPECIAL_DAY = "0229";

	private static final String LEAP_SPECIAL_DAY_PATTERN = "0229 || 0301";

	private static final int TEN_YEAR = 10;

	private static final int TWENTY_YEAR = 20;

	private static Date addTime(Date aDate, int timeType, int amount) {
		if (aDate == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(aDate);
		cal.add(timeType, amount);
		return cal.getTime();
	}

	@Override
	public String getName() {
		return "certCheck";
	}

	@Override
	public AviatorBoolean call(Map<String, Object> env, AviatorObject arg, AviatorObject arg1) {
		String certStartDate = FunctionUtils.getStringValue(arg, env);
		String certExpireDate = FunctionUtils.getStringValue(arg1, env);
		if (StringUtils.isNoneBlank(certStartDate, certExpireDate)) {
			if (!isMailDateDtPartStr(certStartDate)) {
				return AviatorBoolean.FALSE;
			}
			if (!beforeNow(certStartDate)) {
				return AviatorBoolean.FALSE;
			}
			if (CERT_PERMANENT.contains(certExpireDate)) {
				// 长期有效,退出校验
				return AviatorBoolean.TRUE;
			} else if (!isMailDateDtPartStr(certExpireDate)) {
				return AviatorBoolean.FALSE;
			}
			if (!afterNow(certExpireDate)) {
				return AviatorBoolean.FALSE;
			}
			int diffYear = Integer.valueOf(certExpireDate.substring(0, 4)) - Integer.valueOf(certStartDate.substring(0, 4));
			if (diffYear != TEN_YEAR && diffYear != TWENTY_YEAR) {
				return AviatorBoolean.FALSE;
			}
			String certStartDayStr = certStartDate.substring(4, 8);
			String certExpireDayStr = certExpireDate.substring(4, 8);
			if (certStartDayStr.equals(LEAP_SPECIAL_DAY)) {
				if (!LEAP_SPECIAL_DAY_PATTERN.contains(certExpireDayStr)) {
					return AviatorBoolean.FALSE;
				}
			} else {
				if (!certStartDayStr.equals(certExpireDayStr)) {
					return AviatorBoolean.FALSE;
				}
			}
		}
		return AviatorBoolean.TRUE;
	}

	/**
	 * 校验yyyyMMdd格式日期
	 *
	 * @param date
	 * @return
	 */
	private boolean isMailDateDtPartStr(String date) {
		if (StringUtils.isEmpty(date)) {
			return false;
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			sdf.setLenient(false);
			sdf.parse(date);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 校验日期是否晚于当前时间
	 *
	 * @param strDate
	 * @return
	 */
	private boolean afterNow(String strDate) {
		try {
			Date expireDate = parser(strDate, MAIL_DATE_DT_PART_FORMAT);
			Date date = addTime(expireDate, Calendar.MONTH, 1);
			return date.after(new Date());
		} catch (Exception e) {
			throw new ConvertValueException("date parse error", e);
		}
	}

	/**
	 * 校验日期是否早于当前时间
	 *
	 * @param strDate
	 * @return
	 */
	private boolean beforeNow(String strDate) {
		try {
			Date date = parser(strDate, MAIL_DATE_DT_PART_FORMAT);
			return date.before(new Date());
		} catch (Exception e) {
			throw new ConvertValueException("date parse error", e);
		}
	}

	private Date parser(String aDateStr, String pattern) throws ParseException {
		if (StringUtils.isBlank(aDateStr)) {
			return null;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.parse(aDateStr);
	}

}
